package entity

import (
	"database/sql"
	"database/sql/driver"
	"encoding/json"
	"fmt"
	"time"
)

// NullDate 表示一个可以为 NULL 的日期
type NullDate struct {
	Time sql.NullTime
}

// Value 实现 driver.Valuer 接口
func (nd NullDate) Value() (driver.Value, error) {
	if !nd.Time.Valid {
		return nil, nil
	}
	return nd.Time.Time.Format("2006-01-02"), nil
}

// Scan 实现 sql.Scanner 接口
func (nd *NullDate) Scan(value interface{}) error {
	if value == nil {
		nd.Time = sql.NullTime{}
		return nil
	}

	switch v := value.(type) {
	case time.Time:
		nd.Time = sql.NullTime{Time: v, Valid: true}
	case string:
		t, err := time.Parse("2006-01-02", v)
		if err != nil {
			return err
		}
		nd.Time = sql.NullTime{Time: t, Valid: true}
	default:
		return fmt.Errorf("cannot scan type %T into NullDate", value)
	}
	return nil
}

// MarshalJSON 实现 json.Marshaler 接口
func (nd NullDate) MarshalJSON() ([]byte, error) {
	if !nd.Time.Valid {
		return []byte("null"), nil
	}
	return json.Marshal(nd.Time.Time.Format("2006-01-02"))
}

// UnmarshalJSON 实现 json.Unmarshaler 接口
func (nd *NullDate) UnmarshalJSON(data []byte) error {
	if string(data) == "null" {
		nd.Time = sql.NullTime{}
		return nil
	}
	var s string
	if err := json.Unmarshal(data, &s); err != nil {
		return err
	}
	t, err := time.Parse("2006-01-02", s)
	if err != nil {
		return err
	}
	nd.Time = sql.NullTime{Time: t, Valid: true}
	return nil
}
